#include "glshader.h"

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include "glutils.h"

using namespace std;

glShader::glShader()
{
    ProgramObject = 0;
    linker_log = 0;
    is_linked = false;
    _mM = false;
    _noshader = true;

    if (!useGLSL)
    {
        cout << "**ERROR: OpenGL Shading Language is NOT available!" << endl;
    }
    else
    {
        ProgramObject = glCreateProgram();
    }

}

//-----------------------------------------------------------------------------

glShader::~glShader()
{
//    if (linker_log!=0) free(linker_log);
//    if (useGLSL)
//    {
//        for (unsigned int i=0;i<ShaderList.size();i++)
//        {
//            glDetachShader(ProgramObject, ShaderList[i]->ShaderObject);
//            CHECK_GL_ERROR(); // if you get an error here, you deleted the Program object first and then
//            // the ShaderObject! Always delete ShaderObjects last!
//            if (_mM) delete ShaderList[i];
//        }

//        glDeleteShader(ProgramObject);
//        CHECK_GL_ERROR();
//    }

        if (linker_log!=0) free(linker_log);
        if (useGLSL)
        {
            glDeleteProgram(ProgramObject);
            CHECK_GL_ERROR();
            if (_mM){
                for (unsigned int i=0;i<ShaderList.size();i++)
                    delete ShaderList[i];
            }
        }

}
//-----------------------------------------------------------------------------

void glShader::addShader(glShaderObject* ShaderObject)
{
    if (!useGLSL) return;

    if (ShaderObject==0) return;


    if (!ShaderObject->is_compiled)
    {
        cout << "**warning** please compile program before adding object! trying to compile now...\n";
        if (!ShaderObject->compile())
        {
            cout << "...compile ERROR!\n";
            return;
        }
        else
        {
            cout << "...ok!\n";
        }
    }

    ShaderList.push_back(ShaderObject);

}

//-----------------------------------------------------------------------------

void glShader::SetInputPrimitiveType(int nInputPrimitiveType)
{
    _nInputPrimitiveType = nInputPrimitiveType;
}

void glShader::SetOutputPrimitiveType(int nOutputPrimitiveType)
{
    _nOutputPrimitiveType = nOutputPrimitiveType;
}

void glShader::SetVerticesOut(int nVerticesOut)
{
    _nVerticesOut = nVerticesOut;
}
//-----------------------------------------------------------------------------

bool glShader::link(void)
{
    if (!useGLSL) return false;

    unsigned int i;

    if (_bUsesGeometryShader)
    {
        glProgramParameteriEXT(ProgramObject, GL_GEOMETRY_INPUT_TYPE_EXT, _nInputPrimitiveType);
        glProgramParameteriEXT(ProgramObject, GL_GEOMETRY_OUTPUT_TYPE_EXT, _nOutputPrimitiveType);
        glProgramParameteriEXT(ProgramObject, GL_GEOMETRY_VERTICES_OUT_EXT, _nVerticesOut);
    }

    if (is_linked)  // already linked, detach everything first
    {
        cout << "**warning** Object is already linked, trying to link again" << endl;
        for (i=0;i<ShaderList.size();i++)
        {
            glDetachShader(ProgramObject, ShaderList[i]->ShaderObject);
            CHECK_GL_ERROR();
        }
    }

    for (i=0;i<ShaderList.size();i++)
    {
        glAttachShader(ProgramObject, ShaderList[i]->ShaderObject);
        CHECK_GL_ERROR();
        //cout << "attaching ProgramObj [" << i << "] @ 0x" << hex << ShaderList[i]->ProgramObject << " in ShaderObj @ 0x"  << ShaderObject << endl;
    }

    GLint linked; // bugfix Oct-06-2006
    glLinkProgram(ProgramObject);
    CHECK_GL_ERROR();
    glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);
    CHECK_GL_ERROR();

    if (linked)
    {
        is_linked = true;
        return true;
    }
    else
    {
        cout << "**linker error**\n";
    }

    return false;
}

//-----------------------------------------------------------------------------
// Compiler Log: Ausgabe der Compiler Meldungen in String

char* glShader::getLinkerLog(void)
{
    if (!useGLSL) return aGLSLStrings[0];

    GLint blen = 0;    // bugfix Oct-06-2006
    GLsizei slen = 0;  // bugfix Oct-06-2006

    if (ProgramObject==0) return aGLSLStrings[2];
    glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH , &blen);
    CHECK_GL_ERROR();

    if (blen > 1)
    {
        if (linker_log!=0)
        {
            free(linker_log);
            linker_log =0;
        }
        if ((linker_log = (GLcharARB*)malloc(blen)) == NULL)
        {
            printf("ERROR: Could not allocate compiler_log buffer\n");
            return aGLSLStrings[3];
        }

        glGetProgramInfoLog(ProgramObject, blen, &slen, linker_log);
        CHECK_GL_ERROR();

    }
    if (linker_log!=0)
        return (char*) linker_log;
    else
        return aGLSLStrings[5];

    return aGLSLStrings[4];
}

void glShader::begin(void)
{
    if (!useGLSL) return;
    if (ProgramObject == 0) return;
    if (!_noshader) return;

    if (is_linked)
    {
        glUseProgram(ProgramObject);
        CHECK_GL_ERROR();
    }
}

//-----------------------------------------------------------------------------

void glShader::end(void)
{
    if (!useGLSL) return;
    if (!_noshader) return;


    glUseProgram(0);
    CHECK_GL_ERROR();
}

//-----------------------------------------------------------------------------

bool glShader::setUniform1f(GLcharARB* varname, GLfloat v0, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index


    glUniform1f(loc, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform2f(GLcharARB* varname, GLfloat v0, GLfloat v1, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2f(loc, v0, v1);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3f(GLcharARB* varname, GLfloat v0, GLfloat v1, GLfloat v2, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3f(loc, v0, v1, v2);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4f(GLcharARB* varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4f(loc, v0, v1, v2, v3);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform1i(GLcharARB* varname, GLint v0, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform1i(loc, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform2i(GLcharARB* varname, GLint v0, GLint v1, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2i(loc, v0, v1);


    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3i(GLcharARB* varname, GLint v0, GLint v1, GLint v2, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3i(loc, v0, v1, v2);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4i(GLcharARB* varname, GLint v0, GLint v1, GLint v2, GLint v3, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4i(loc, v0, v1, v2, v3);

    return true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

bool glShader::setUniform1ui(GLcharARB* varname, GLuint v0, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform1uiEXT(loc, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform2ui(GLcharARB* varname, GLuint v0, GLuint v1, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2uiEXT(loc, v0, v1);


    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3ui(GLcharARB* varname, GLuint v0, GLuint v1, GLuint v2, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3uiEXT(loc, v0, v1, v2);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4ui(GLcharARB* varname, GLuint v0, GLuint v1, GLuint v2, GLuint v3, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4uiEXT(loc, v0, v1, v2, v3);

    return true;
}
//-----------------------------------------------------------------------------

bool glShader::setUniform1fv(GLcharARB* varname, GLsizei count, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform1fv(loc, count, value);

    return true;
}
bool glShader::setUniform2fv(GLcharARB* varname, GLsizei count, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2fv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3fv(GLcharARB* varname, GLsizei count, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3fv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4fv(GLcharARB* varname, GLsizei count, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4fv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform1iv(GLcharARB* varname, GLsizei count, GLint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform1iv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform2iv(GLcharARB* varname, GLsizei count, GLint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2iv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3iv(GLcharARB* varname, GLsizei count, GLint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3iv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4iv(GLcharARB* varname, GLsizei count, GLint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4iv(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform1uiv(GLcharARB* varname, GLsizei count, GLuint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform1uivEXT(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform2uiv(GLcharARB* varname, GLsizei count, GLuint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform2uivEXT(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform3uiv(GLcharARB* varname, GLsizei count, GLuint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform3uivEXT(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniform4uiv(GLcharARB* varname, GLsizei count, GLuint *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniform4uivEXT(loc, count, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniformMatrix2fv(GLcharARB* varname, GLsizei count, GLboolean transpose, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniformMatrix2fv(loc, count, transpose, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniformMatrix3fv(GLcharARB* varname, GLsizei count, GLboolean transpose, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniformMatrix3fv(loc, count, transpose, value);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setUniformMatrix4fv(GLcharARB* varname, GLsizei count, GLboolean transpose, GLfloat *value, GLint index)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return false;  // can't find variable / invalid index

    glUniformMatrix4fv(loc, count, transpose, value);

    return true;
}

//-----------------------------------------------------------------------------

GLint glShader::GetUniformLocation(const GLcharARB *name)
{
    GLint loc;

    loc = glGetUniformLocation(ProgramObject, name);
    if (loc == -1)
    {
        cout << "Error: can't find uniform variable \"" << name << "\"\n";
    }
    CHECK_GL_ERROR();
    return loc;
}

//-----------------------------------------------------------------------------

void glShader::getUniformfv(GLcharARB* varname, GLfloat* values, GLint index)
{
    if (!useGLSL) return;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return;  // can't find variable / invalid index

    glGetUniformfv(ProgramObject, loc, values);

}

//-----------------------------------------------------------------------------

void glShader::getUniformiv(GLcharARB* varname, GLint* values, GLint index)
{
    if (!useGLSL) return;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return;  // can't find variable / invalid index

    glGetUniformiv(ProgramObject, loc, values);

}

//-----------------------------------------------------------------------------

void glShader::getUniformuiv(GLcharARB* varname, GLuint* values, GLint index)
{
    if (!useGLSL) return;

    GLint loc;
    if (varname)
        loc = GetUniformLocation(varname);
    else
        loc = index;

    if (loc==-1)
        return;  // can't find variable / invalid index

    glGetUniformuivEXT(ProgramObject, loc, values);

}

//-----------------------------------------------------------------------------
void  glShader::BindAttribLocation(GLint index, GLchar* name)
{
    glBindAttribLocation(ProgramObject, index, name);
}

//-----------------------------------------------------------------------------


bool glShader::setVertexAttrib1f(GLuint index, GLfloat v0)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib1f(index, v0);

    return true;
}

bool glShader::setVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib2f(index, v0, v1);

    return true;
}

bool glShader::setVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib3f(index, v0, v1, v2);

    return true;
}

bool glShader::setVertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib4f(index, v0, v1, v2, v3);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib1d(GLuint index, GLdouble v0)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib1d(index, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib2d(GLuint index, GLdouble v0, GLdouble v1)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib2d(index, v0, v1);

    return true;
}

//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib3d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib3d(index, v0, v1, v2);

    return true;
}
//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib4d(GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib4d(index, v0, v1, v2, v3);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib1s(GLuint index, GLshort v0)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib1s(index, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib2s(GLuint index, GLshort v0, GLshort v1)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib2s(index, v0, v1);

    return true;
}

//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib3s(GLuint index, GLshort v0, GLshort v1, GLshort v2)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib3s(index, v0, v1, v2);

    return true;
}
//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib4s(GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib4s(index, v0, v1, v2, v3);

    return true;
}
//----------------------------------------------------------------------------
bool glShader::setVertexAttribNormalizedByte(GLuint index, GLbyte v0, GLbyte v1, GLbyte v2, GLbyte v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!_noshader) return true;

    glVertexAttrib4Nub(index, v0, v1, v2, v3);

    return true;
}
//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib1i(GLuint index, GLint v0)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI1iEXT(index, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib2i(GLuint index, GLint v0, GLint v1)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI2iEXT(index, v0, v1);

    return true;
}

//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib3i(GLuint index, GLint v0, GLint v1, GLint v2)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI3iEXT(index, v0, v1, v2);

    return true;
}
//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib4i(GLuint index, GLint v0, GLint v1, GLint v2, GLint v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI4iEXT(index, v0, v1, v2, v3);

    return true;
}
//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib1ui(GLuint index, GLuint v0)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI1uiEXT(index, v0);

    return true;
}

//-----------------------------------------------------------------------------

bool glShader::setVertexAttrib2ui(GLuint index, GLuint v0, GLuint v1)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI2uiEXT(index, v0, v1);

    return true;
}

//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib3ui(GLuint index, GLuint v0, GLuint v1, GLuint v2)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI3uiEXT(index, v0, v1, v2);

    return true;
}
//-----------------------------------------------------------------------------
bool glShader::setVertexAttrib4ui(GLuint index, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
{
    if (!useGLSL) return false; // GLSL not available
    if (!bGPUShader4) return false;
    if (!_noshader) return true;

    glVertexAttribI4uiEXT(index, v0, v1, v2, v3);

    return true;
}

//-----------------------------------------------------------------------------
//glm data types manipulation
void glShader::setUniform(char *name, const vec3 &v)
{
    this->setUniform(name, v.x, v.y, v.z);
}


void glShader::setUniform(char *name, const vec4 &v)
{
    int loc = GetUniformLocation(name);
    if (loc >= 0)
        glUniform4f(loc, v.x, v.y, v.z, v.w);
    else
        printf("Uniform: %s not found.\n", name);
}

void glShader::setUniform(char *name, const mat3 &m)
{
    int loc = GetUniformLocation(name);
    if( loc >= 0 )
        glUniformMatrix3fv(loc, 1, GL_FALSE, &m[0][0]);
    else
        printf("Uniform: %s not found.\n",name);
}

void glShader::setUniform(char *name, const mat4 & m)
{
    int loc = GetUniformLocation(name);
    if( loc >= 0 )
        glUniformMatrix4fv(loc, 1, GL_FALSE, &m[0][0]);
    else
        printf("Uniform: %s not found.\n",name);

}

void glShader::setUniform(char *name, float x, float y, float z)
{
    int loc = GetUniformLocation(name);
    if (loc >= 0)
        glUniform3f(loc, x, y, z);
    else
        printf("Uniform: %s not found.\n", name);
}
